<?php
/*
# ------------------------------------------------------------------------
# JA Compress Plugin for Joomla 1.5
# ------------------------------------------------------------------------
# Copyright (C) 2004-2009 J.O.O.M Solutions Co., Ltd. All Rights Reserved.
# @license - GNU/GPL, http://www.gnu.org/copyleft/gpl.html
# Author: J.O.O.M Solutions Co., Ltd
# Websites:  http://www.joomlart.com -  http://www.joomlancers.com
# ------------------------------------------------------------------------
*/

// Prevent direct access
defined( '_JEXEC' ) or die();

// Import required library
jimport( 'joomla.plugin.plugin' );
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');
jimport('joomla.application.module.helper');

/**
 * JACompress Content Plugin
 *
 * @package		Joomla
 * @subpackage	System
 * @since 		1.5
 */
class plgSystemPlg_JACompress extends JPlugin
{
	// Plugin paramater
	var $_params;
	
	// Constructor
	function plgSystemPlg_JACompress( &$subject ){
		parent::__construct( $subject );
		
		// Load plugin parameters
		$_plugin = JPluginHelper::getPlugin( 'system', 'plg_jacompress' );
		$this->_params 		= new JParameter( $_plugin->params );
	}
	
	function setSmartOptimizerConfigFile(){
		// Create cache folder
		JFolder::create(JPATH_CACHE.DS."jacompress".DS."smartoptimizer");
		// Read config file content and Write to it.
		$content = JFile::read(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."smartoptimizer".DS."config.php");
		$content = explode("\n", $content);
		
		if (stristr(PHP_OS, 'WIN')) { 
			$path1 = str_replace(DS, "/", JPATH_ROOT.DS);
			$path2 = str_replace(DS, "/", JPATH_ROOT.DS.'cache'.DS.'jacompress'.DS.'smartoptimizer'.DS);
		} else { 
		 	$path1 = JPATH_ROOT.DS;
			$path2 = JPATH_ROOT.DS.'cache'.DS.'jacompress'.DS.'smartoptimizer'.DS;
		}
		
		$content[7] 	= '$settings[\'baseDir\'] = "'.$path1."\";";
		$content[49] 	= '$settings[\'cacheDir\'] = \''.$path2.'\';';
		
		foreach($content as $key=>$string){
			preg_match_all("/\['(.*)'\]/i", $string, $arrMatchs);
			if(isset($arrMatchs[1][0])){
				$string = $arrMatchs[1][0];
				$value  = $this->_params->get("general-smartoptimizer-".$string);				
				if(isset($value) && $value != ""){
					$content[$key] = '$settings[\''.$string."'] = '".$value."';";				
				}				
			}
		}
		JFile::write(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."smartoptimizer".DS."config.php", implode("\n", $content));
	}
	
	function setMinifyConfigFile(){
		// Create cache folder
		JFolder::create(JPATH_CACHE.DS."jacompress".DS."minify");
		// Read config file content and Write to it.
		$content = JFile::read(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."minify".DS."config.php");
		$content = explode("\n", $content);
		
		if (stristr(PHP_OS, 'WIN')) {
			$path1 = str_replace(DS, "/", JPATH_ROOT.DS);
			$path2 = str_replace(DS, "/", JPATH_ROOT.DS.'cache'.DS.'jacompress'.DS.'minify'.DS);
		} else {
			$path1 = JPATH_ROOT.DS;
			$path2 = JPATH_ROOT.DS.'cache'.DS.'jacompress'.DS.'minify'.DS;
		}
		
		$content[13] = '$min_allowDebugFlag = '.$this->_params->get("general-minify-debug", "1").';';
		$content[40] = '$min_cachePath = \''.$path2.'\';';
		$content[54] = '$min_documentRoot = \''.$path1.'\';';
		$content[86] = '$min_serveOptions[\'maxAge\'] = '.($this->_params->get("general-minify-browsercachetime", "30")*60).';';
		
		JFile::write(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."minify".DS."config.php", implode("\n", $content));
	}
	
	function setMinifyGroupConfigFile($groupName, $files){
		// Read config file content and Write to it.
		$content = JFile::read(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."minify".DS."groupsConfig.php");
		$content = explode("\n", $content);
		
		$files = str_replace(",", "', '", "'".$files."'");
		$files = str_replace("', ''", "'", $files);
		
		$exist = false;
		foreach ($content as $k=>$cont){
			if(strpos($cont, $groupName) !== false){
				$content[$k] = " '{$groupName}' => array(".$files."), ";
				$exist = true;
			}
		}
		
		if(!$exist){
			$content[count($content)-1] = " '{$groupName}' => array(".$files."), ";
			$content[] = ");";
		}
		
		JFile::write(JPATH_PLUGINS.DS."system".DS."plg_jacompress".DS."minify".DS."groupsConfig.php", implode("\n", $content));
	}
	
	function replaceWithLibrary($bodyString, $type, $arrAvoid, $merge=1){
		// Prepair link
		$lib = $this->_params->get("general", "smartoptimizer");
		if ($lib == "smartoptimizer"){
			$strLink = JURI::root()."plugins/system/plg_jacompress/smartoptimizer/?";
			$strFullLink = ($type=="js")?'<script language="javascript" charset="utf-8" type="text/javascript" src="'.$strLink.'"></script>':'<link rel="stylesheet" href="'.$strLink.'" type="text/css" />';
		}else{
			$strLink = JURI::root()."plugins/system/plg_jacompress/minify/?f=";
			$strFullLink = ($type=="js")?'<script language="javascript" charset="utf-8" type="text/javascript" src="'.$strLink.'"></script>':'<link rel="stylesheet" href="'.$strLink.'" type="text/css" />';			
		}
		
		// Find script
		$scriptRegex = ($type=="js")?"/<script[^>]*?>[\s\S]*?<\/script>/i":"/<link [^>]+(\/>)/i";
		preg_match_all($scriptRegex, $bodyString, $matches);
		
		// Find link...
		$regString = "/([^\"\'=]+\.(".$type."))[\"\']/i";	
		$remotePath = str_replace(str_replace(DS, "/", $_SERVER['DOCUMENT_ROOT']), "", str_replace(DS, "/", JPATH_SITE)) . '/';
		
		$strMerge = "";
		$strPath = "";
		
		foreach ($matches[0] as $match){
			preg_match_all($regString, $match, $arrMatchs);
			if(isset($arrMatchs[1][0])){
				$filePath = $arrMatchs[1][0];
				if(strpos($filePath, 'http') !== 0) {
					$strTemp = substr($filePath, strlen($remotePath));
				} else {
					if(strpos($filePath, JURI::root()) === false)
						continue;
					$strTemp = "/".substr($filePath, strlen(JURI::root()));
				}
				$strTemp = str_replace("//", "/", $strTemp);
				
				if(!file_exists(str_replace(DS, "/", JPATH_SITE)."/".$strTemp))
					continue;
				
				$replace = true;
				if($arrAvoid != ''){
					foreach ($arrAvoid as $string){
						if( strpos($filePath, $string) !== false  && $string != ''){
							$replace = false;
							if($type == "js" && $lib == "minify" && $strMerge != ""){
								preg_match_all("/<script[^>]*?>[\s\S]*?<\/script>/i", $match, $result);
								if(isset($result[0][0])){
									$strMerge = substr($strMerge, 0, strlen($strMerge)-1);
									$bodyString = str_replace($match, str_replace($strLink, $strLink.$strMerge, $strFullLink)."\n".$match, $bodyString);
									$strMerge = "";
								}
							}							
							break;
						}
					}
				}
				// Replace with another link
				if($replace){
					// Not merge files
					if($merge == 0){
						$strTemp = $strLink.$strTemp;
						$bodyString = str_replace($filePath, $strTemp, $bodyString);
					}
					if($merge == 1){
						// Merge files
						$strReplace = "";
						if($lib == "minify"){
							$strMerge .= $strTemp.",";
						}else{
							$tmp = $this->detachFilePath($strTemp);	
							
							if($strPath != "" && $tmp[0] != $strPath && $strMerge != ""){
								// Begin add links.
								$strMerge = substr($strMerge, 0, strlen($strMerge)-1);
								if($type == "css")
									$bodyString = str_replace("</title>", "</title>\n".str_replace($strLink, $strLink.$strPath.$strMerge, $strFullLink), $bodyString);
								else{
									$strReplace = str_replace($strLink, $strLink.$strPath.$strMerge, $strFullLink);
								}
								$strMerge = "";
							}
							$strMerge	.= $tmp[1].",";
							$strPath 	= $tmp[0];
						}
						// Remove link to css, js file
						foreach ($matches[0] as $string){
							if(strpos($string, $filePath) !== false){
								$bodyString = str_replace($string, $strReplace, $bodyString);
							}
						}					
					}				
				}else{
					// Get avoid files
					
				}
			}else{
				// Process internal javascript
				if($type == "js" && $strMerge != "" && $merge == 1){
					preg_match_all("/<script[^>]*?>[\s\S]*?<\/script>/i", $match, $result);
					if(isset($result[0][0])){
						$strMerge = substr($strMerge, 0, strlen($strMerge)-1);
						if($lib == "minify")
							$bodyString = str_replace($match, str_replace($strLink, $strLink.$strMerge, $strFullLink)."\n".$match, $bodyString);
						elseif($lib == "smartoptimizer" && $strPath != ""){
							$bodyString = str_replace($match, str_replace($strLink, $strLink.$strPath.$strMerge, $strFullLink)."\n".$match, $bodyString);
						}
						$strMerge = "";
					}
				}
			}
		}
		
		// Merge file
		if($merge == "1" && $strMerge != ""){
			$strMerge = substr($strMerge, 0, strlen($strMerge)-1);
			if($lib == "minify"){			
				$bodyString = str_replace("</title>", "</title>\n".str_replace($strLink, $strLink.$strMerge, $strFullLink), $bodyString);
			}else{
				if(strpos($bodyString, $strLink.$strPath.$strMerge) === false){
					if($type == "css"){
						$bodyString = str_replace("</title>", "</title>\n".str_replace($strLink, $strLink.$strPath.$strMerge, $strFullLink), $bodyString);
					}else{
						$bodyString = $bodyString.str_replace($strLink, $strLink.$strPath.$strMerge, $strFullLink);
					}
				}
			}
		}
		
		return $bodyString;
	}
	
	function detachFilePath($string){
		return str_split($string, strrpos($string, "/")+1);
	}
	
	/* Get list of CSS link avoid by: <!--[if ... <![endif]-->*/
	function getExcludeCSSByCondition($bodyString){
		// Find script		
		$scriptRegex = "/<!--\[if[^\]]*?\][\s\S]*?<!\[endif\]-->/i";
		preg_match_all($scriptRegex, $bodyString, $matches);
		$regString = "/([^\"\'=]+\.(css))[\"\']/i";
		
		if(isset($matches[0]))
			preg_match_all($regString, implode("", $matches[0]), $arrMatchs);
		else
			return array();
		
		if(isset($arrMatchs[1]))
			return $arrMatchs[1];
		else
			return array();
	}
	
	/**
	 * Replace header library method
	 *
	 * @param 	string		The body string content.
	 */	
	function replaceLink( $bodyString ){
		// Optimize CSS files
		
		if ($this->_params->get("css-enable", "0") == "1"){
			$avoid = $this->_params->get("css-avoid", "");
			if(!is_array($avoid)){
				$avoid = ($avoid != '')?array($avoid):array();
				$avoid = array_merge($avoid, $this->getExcludeCSSByCondition($bodyString));
			}
			$merge = $this->_params->get("css-merge", "0");
			$bodyString = $this->replaceWithLibrary($bodyString, "css", $avoid, $merge);
		}
		
		if ($this->_params->get("js-enable", "0") == "1"){
			$avoid = $this->_params->get("js-avoid", "");
			if(!is_array($avoid)){
				$avoid = ($avoid != '')?array($avoid):"";
			}
			$merge = $this->_params->get("js-merge", "0");
			$bodyString = $this->replaceWithLibrary($bodyString, "js", $avoid, $merge);
		}
		
		return $bodyString;
	}
	
	function onAfterRender(){
		// Return if page is not front-end
		global $mainframe;
		if ( $mainframe->isAdmin() ) { return; }
		
		// Return if page is not in HTML format
		$document	=& JFactory::getDocument();		
		$doctype	= $document->getType();
		if ( $doctype != 'html' ) { return; }
		
		// Write to config file
		if ($this->_params->get("general", "smartoptimizer") == "smartoptimizer"){
			$this->setSmartOptimizerConfigFile();
		}else{
			$this->setMinifyConfigFile();
		}
		
		// Get body string after render
		$_body = JResponse::getBody();
		$_body = explode("</head>", $_body, 2);
		// Replace CSS library
		$_body[0] = $this->replaceLink($_body[0]);
		$_body = $_body[0]."</head>".$_body[1];
		
		if ( $_body ) {
			JResponse::setBody( $_body );
		}
		return true;
	}
}
?>